<template>
  <div class="transfer-container">
    <div class="transfer-panel">
      <div class="transfer-header">
        <span class="transfer-title">{{ leftTitle }}</span>
        <span class="transfer-count">{{ leftCheckedCount }}/{{ leftData.length }}</span>
      </div>
      <div class="transfer-body">
        <div class="transfer-search" v-if="filterable">
          <input
            type="text"
            v-model="leftFilterText"
            :placeholder="filterPlaceholder"
            class="transfer-search-input"
          />
        </div>
        <div class="transfer-list" :style="{ height: listHeight }">
          <div v-if="filteredLeftData.length === 0" class="transfer-empty">
            {{ leftFilterText ? '无匹配数据' : '暂无数据' }}
          </div>
          <label
            v-for="item in filteredLeftData"
            :key="item[keyProp]"
            class="transfer-item"
            :class="{ 
              'is-disabled': item.disabled,
              'is-checked': leftChecked.includes(item[keyProp])
            }"
            @click="!item.disabled && toggleLeftItem(item[keyProp])"
          >
            <input
              type="checkbox"
              :value="item[keyProp]"
              v-model="leftChecked"
              :disabled="item.disabled"
              class="transfer-checkbox"
              @click.stop
            />
            <span class="transfer-item-text">{{ renderLabel(item) }}</span>
          </label>
        </div>
      </div>
      <div class="transfer-footer" v-if="showAllBtn">
        <label class="transfer-checkbox-all" @click="leftCheckAll = !leftCheckAll">
          <input
            type="checkbox"
            :indeterminate.prop="leftIndeterminate"
            v-model="leftCheckAll"
            class="transfer-checkbox"
            @click.stop
          />
          <span>全选</span>
        </label>
      </div>
    </div>

    <div class="transfer-buttons">
      <button
        class="transfer-button"
        :disabled="leftChecked.length === 0"
        @click="moveToRight"
        :title="`向右移动 ${leftChecked.length} 项`"
      >
        <span>→</span>
      </button>
      <button
        class="transfer-button"
        :disabled="rightChecked.length === 0"
        @click="moveToLeft"
        :title="`向左移动 ${rightChecked.length} 项`"
      >
        <span>←</span>
      </button>
    </div>

    <div class="transfer-panel">
      <div class="transfer-header">
        <span class="transfer-title">{{ rightTitle }}</span>
        <span class="transfer-count">{{ rightCheckedCount }}/{{ rightData.length }}</span>
      </div>
      <div class="transfer-body">
        <div class="transfer-search" v-if="filterable">
          <input
            type="text"
            v-model="rightFilterText"
            :placeholder="filterPlaceholder"
            class="transfer-search-input"
          />
        </div>
        <div class="transfer-list" :style="{ height: listHeight }">
          <div v-if="filteredRightData.length === 0" class="transfer-empty">
            {{ rightFilterText ? '无匹配数据' : '暂无数据' }}
          </div>
          <label
            v-for="item in filteredRightData"
            :key="item[keyProp]"
            class="transfer-item"
            :class="{ 
              'is-disabled': item.disabled,
              'is-checked': rightChecked.includes(item[keyProp])
            }"
            @click="!item.disabled && toggleRightItem(item[keyProp])"
          >
            <input
              type="checkbox"
              :value="item[keyProp]"
              v-model="rightChecked"
              :disabled="item.disabled"
              class="transfer-checkbox"
              @click.stop
            />
            <span class="transfer-item-text">{{ renderLabel(item) }}</span>
          </label>
        </div>
      </div>
      <div class="transfer-footer" v-if="showAllBtn">
        <label class="transfer-checkbox-all" @click="rightCheckAll = !rightCheckAll">
          <input
            type="checkbox"
            :indeterminate.prop="rightIndeterminate"
            v-model="rightCheckAll"
            class="transfer-checkbox"
            @click.stop
          />
          <span>全选</span>
        </label>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Transfer',
  props: {
    data: {
      type: Array,
      default: () => []
    },
    value: {
      type: Array,
      default: () => []
    },
    leftTitle: {
      type: String,
      default: '待选项'
    },
    rightTitle: {
      type: String,
      default: '已选项'
    },
    filterable: {
      type: Boolean,
      default: false
    },
    filterPlaceholder: {
      type: String,
      default: '请输入搜索内容'
    },
    keyProp: {
      type: String,
      default: 'key'
    },
    labelProp: {
      type: String,
      default: 'label'
    },
    listHeight: {
      type: String,
      default: '200px'
    },
    showAllBtn: {
      type: Boolean,
      default: true
    },
    renderContent: {
      type: Function,
      default: null
    }
  },
  data() {
    return {
      leftChecked: [],
      rightChecked: [],
      leftFilterText: '',
      rightFilterText: ''
    }
  },
  computed: {
    leftData() {
      return this.data.filter(item => !this.value.includes(item[this.keyProp]))
    },
    rightData() {
      return this.data.filter(item => this.value.includes(item[this.keyProp]))
    },
    filteredLeftData() {
      if (!this.filterable || !this.leftFilterText) {
        return this.leftData
      }
      return this.leftData.filter(item => 
        this.renderLabel(item).toLowerCase().includes(this.leftFilterText.toLowerCase())
      )
    },
    filteredRightData() {
      if (!this.filterable || !this.rightFilterText) {
        return this.rightData
      }
      return this.rightData.filter(item => 
        this.renderLabel(item).toLowerCase().includes(this.rightFilterText.toLowerCase())
      )
    },
    leftCheckedCount() {
      return this.leftChecked.length
    },
    rightCheckedCount() {
      return this.rightChecked.length
    },
    leftIndeterminate() {
      const count = this.leftCheckedCount
      const total = this.filteredLeftData.filter(item => !item.disabled).length
      return count > 0 && count < total
    },
    rightIndeterminate() {
      const count = this.rightCheckedCount
      const total = this.filteredRightData.filter(item => !item.disabled).length
      return count > 0 && count < total
    },
    leftCheckAll: {
      get() {
        const enabledData = this.filteredLeftData.filter(item => !item.disabled)
        return enabledData.length > 0 && this.leftCheckedCount === enabledData.length
      },
      set(val) {
        if (val) {
          this.leftChecked = this.filteredLeftData
            .filter(item => !item.disabled)
            .map(item => item[this.keyProp])
        } else {
          this.leftChecked = []
        }
      }
    },
    rightCheckAll: {
      get() {
        const enabledData = this.filteredRightData.filter(item => !item.disabled)
        return enabledData.length > 0 && this.rightCheckedCount === enabledData.length
      },
      set(val) {
        if (val) {
          this.rightChecked = this.filteredRightData
            .filter(item => !item.disabled)
            .map(item => item[this.keyProp])
        } else {
          this.rightChecked = []
        }
      }
    }
  },
  watch: {
    value: {
      handler(newVal) {
        // 清理不存在的选中项
        this.leftChecked = this.leftChecked.filter(key => 
          this.leftData.some(item => item[this.keyProp] === key)
        )
        this.rightChecked = this.rightChecked.filter(key => 
          this.rightData.some(item => item[this.keyProp] === key)
        )
      },
      immediate: true
    }
  },
  methods: {
    renderLabel(item) {
      if (this.renderContent) {
        return this.renderContent(item)
      }
      return item[this.labelProp]
    },
    toggleLeftItem(key) {
      const index = this.leftChecked.indexOf(key)
      if (index > -1) {
        this.leftChecked.splice(index, 1)
      } else {
        this.leftChecked.push(key)
      }
    },
    toggleRightItem(key) {
      const index = this.rightChecked.indexOf(key)
      if (index > -1) {
        this.rightChecked.splice(index, 1)
      } else {
        this.rightChecked.push(key)
      }
    },
    moveToRight() {
      const newValue = [...this.value, ...this.leftChecked]
      this.$emit('input', newValue)
      this.$emit('change', newValue, 'right', this.leftChecked)
      this.leftChecked = []
    },
    moveToLeft() {
      const newValue = this.value.filter(key => !this.rightChecked.includes(key))
      this.$emit('input', newValue)
      this.$emit('change', newValue, 'left', this.rightChecked)
      this.rightChecked = []
    }
  }
}
</script>

<style scoped>
.transfer-container {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  font-size: 14px;
}

.transfer-panel {
  width: 200px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.transfer-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: #f5f7fa;
  border-bottom: 1px solid #dcdfe6;
}

.transfer-title {
  font-weight: 500;
  color: #303133;
}

.transfer-count {
  color: #909399;
  font-size: 12px;
}

.transfer-body {
  position: relative;
}

.transfer-search {
  padding: 12px 16px;
  border-bottom: 1px solid #dcdfe6;
}

.transfer-search-input {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  font-size: 14px;
  box-sizing: border-box;
  transition: border-color 0.2s;
}

.transfer-search-input:focus {
  outline: none;
  border-color: #409eff;
}

.transfer-list {
  overflow-y: auto;
  padding: 8px 0;
  max-height: 300px;
}

.transfer-list::-webkit-scrollbar {
  width: 6px;
}

.transfer-list::-webkit-scrollbar-track {
  background: #f1f1f1;
}

.transfer-list::-webkit-scrollbar-thumb {
  background: #c0c4cc;
  border-radius: 3px;
}

.transfer-list::-webkit-scrollbar-thumb:hover {
  background: #909399;
}

.transfer-empty {
  padding: 16px;
  text-align: center;
  color: #909399;
  font-size: 12px;
}

.transfer-item {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  cursor: pointer;
  user-select: none;
  transition: background-color 0.2s;
}

.transfer-item:hover {
  background: #f5f7fa;
}

.transfer-item.is-checked {
  background: #f0f9ff;
  color: #409eff;
}

.transfer-item.is-disabled {
  color: #c0c4cc;
  cursor: not-allowed;
}

.transfer-item.is-disabled:hover {
  background: transparent;
}

.transfer-checkbox {
  margin-right: 8px;
  cursor: pointer;
}

.transfer-item.is-disabled .transfer-checkbox {
  cursor: not-allowed;
}

.transfer-item-text {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.transfer-footer {
  padding: 12px 16px;
  border-top: 1px solid #dcdfe6;
  background: #f5f7fa;
}

.transfer-checkbox-all {
  display: flex;
  align-items: center;
  cursor: pointer;
  user-select: none;
}

.transfer-buttons {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-self: center;
}

.transfer-button {
  width: 32px;
  height: 32px;
  border: 1px solid #dcdfe6;
  border-radius: 50%;
  background: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
}

.transfer-button:hover:not(:disabled) {
  background: #409eff;
  border-color: #409eff;
  color: #fff;
  transform: scale(1.05);
}

.transfer-button:disabled {
  background: #f5f7fa;
  border-color: #e4e7ed;
  color: #c0c4cc;
  cursor: not-allowed;
}

.transfer-button span {
  font-size: 16px;
  font-weight: bold;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .transfer-container {
    flex-direction: column;
    gap: 12px;
  }
  
  .transfer-panel {
    width: 100%;
    min-width: 280px;
  }
  
  .transfer-buttons {
    flex-direction: row;
    justify-content: center;
    align-self: center;
  }
  
  .transfer-button {
    width: 40px;
    height: 40px;
  }
}
</style>